package org.batyrov.equery.server;

import org.apache.log4j.LogManager;

import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.io.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Iterator;


/**
 * Created by IntelliJ IDEA.
 * User: admin
 * Date: 12.09.2009
 * Time: 19:35:35
 * To change this template use File | Settings | File Templates.
 */

public class Server implements Runnable{
    private static Server _server;
    private static Thread thread;
    Socket s = null;

    private boolean status = true;
    private ServerSocket serverSocket;
    private static BlockingQueue<SocketProcessor> equery = new LinkedBlockingQueue<SocketProcessor>();


    public BlockingQueue<SocketProcessor> getEquery() {
        return equery;
    }

    public static Server getInstance() {
        if (_server == null){
            _server = new Server(1234);
            thread = new Thread(_server);
            thread.start();
        }
        return _server;
    }

    private Server(int port) {
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private Socket getNewConn() {
        try {
            s = serverSocket.accept();
        } catch (IOException ignored) {}
        return s;
    }

    public static void removeByQuery(SocketAddress socketAddress){
        Iterator iter = equery.iterator();
        while(iter.hasNext()){
            SocketProcessor sock = ((SocketProcessor)iter.next());
            if(sock._socket.getRemoteSocketAddress().equals(socketAddress)){
                equery.remove(sock);
                System.out.println("Client with address" + socketAddress + "closed");
                sock.close();
            }
        }
    }

    public void CallClient(int clientNumber, String windowNumber) {
        for (SocketProcessor socketProcessor : equery) {
            socketProcessor.send(clientNumber + " " + windowNumber);
        }
    }

    @Override
    public void run() {
        while (true) {
            Socket s = getNewConn();
            if (Thread.currentThread().isInterrupted()) {
                break;
            } else if (s != null && !s.isClosed()) {
                try {
                    SocketProcessor processor = new SocketProcessor(s);
                    equery.offer(processor);
                }
                catch (IOException ignored) {
                    ignored.printStackTrace();
                }
            }
        }
    }

    public void shutdown() {
        System.out.println("SocketProcessor close");
        for(SocketProcessor socketProcessor:equery){
            socketProcessor.close();
            socketProcessor = null;
        }
        equery.clear();
        equery = null;
        status = false;
        try {
            System.out.println("Server close");
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Server._server = null;
        System.out.println("Shutdown finished");
        System.exit(0);
    }
}
